package org.extframework.ld.service.pojo;

import java.sql.SQLException;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang.StringUtils;
import org.extframework.ld.bean.Entity;
import org.extframework.ld.service.CommDao;
import org.hibernate.Criteria;
import org.hibernate.HibernateException;
import org.hibernate.LockMode;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.criterion.Expression;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.orm.hibernate3.HibernateCallback;
import org.springframework.orm.hibernate3.support.HibernateDaoSupport;

/**
 * @author : Dong.Li
 * @created : 2013-1-17
 * @version : 1.0
 * @description :数据库操作
 */
@SuppressWarnings("unchecked")
public class DefaultCommDao extends HibernateDaoSupport implements CommDao {

	private SessionFactory sessionFactory;

	public <T extends Entity> T get(Class<T> paramClass, Long id) {
		return getHibernateTemplate().get(paramClass, id);
	}

	public <T extends Entity> T load(Class<T> paramClass, Long id) {
		return getHibernateTemplate().load(paramClass, id);
	}

	public <T extends Entity> List<T> loadAll(final Class<T> paramClass,
			final Long[] ids) {
		return ((List) getHibernateTemplate().execute(
				new HibernateCallback<Object>() {
					public Object doInHibernate(Session session)
							throws HibernateException, SQLException {
						@SuppressWarnings("deprecation")
						Criteria criteria = session.createCriteria(paramClass)
								.add(Expression.in("id", ids));
						return (T) criteria.list();
					}

				}));
	}

	
	public <T extends Entity> List<T> loadAll(Class<T> paramClass) {
		return getHibernateTemplate().loadAll(paramClass);
	}

	
	public <T extends Entity> List<T> loadAll(Class<T> paramClass,
			List<Long> paramList) {
		return loadAll(paramClass, paramList.toArray(new Long[0]));
	}

	
	public <T extends Entity> void store(T paramT) {
		getHibernateTemplate().saveOrUpdate(paramT);
	}

	
	public <T extends Entity> void delete(T paramT) {
		getHibernateTemplate().delete(paramT);
	}

	
	public <T extends Entity> void deleteAll(Collection<T> paramCollection) {
		getHibernateTemplate().deleteAll(paramCollection);
	}

	
	public void initialize(Object paramObject) {
		getHibernateTemplate().initialize(paramObject);
	}

	
	public void refresh(Object paramObject) {
		getHibernateTemplate().lock(paramObject, LockMode.READ);
	}

	
	public List query(final String hql, final Map paramMap) {
		return getHibernateTemplate().executeFind(
				new HibernateCallback<Object>() {

					
					public Object doInHibernate(Session session)
							throws HibernateException, SQLException {

						Query query = session.createQuery(hql);
						for (Iterator i = paramMap.keySet().iterator(); i
								.hasNext();) {
							String key = (String) i.next();
							Object value = paramMap.get(key);
							query.setParameter(key, value);
						}
						return query.list();
					}
				});
	}

	
	public List findByQuery(String hql, String param, Object value) {
		return findByQuery(hql, new String[] { param }, new Object[] { value });
	}

	
	public List findByQuery(String hql) {
		return findByQuery(hql, new String[0], new Object[0]);
	}

	
	public List findByQuery(final String hql, final String[] params,
			final Object[] values) {
		return ((List) getHibernateTemplate().execute(
				new HibernateCallback<Object>() {
					public Object doInHibernate(Session session)
							throws HibernateException, SQLException {
						Query query = session.createQuery(hql);
						query.getReturnAliases();
						if (values != null) {
							for (int i = 0; i < params.length; ++i) {
								if (StringUtils.isEmpty(params[i]))
									continue;
								if ((values != null)
										&& (Collection.class
												.isAssignableFrom(values
														.getClass())))
									query.setParameterList(params[i],
											(Collection) values[i]);
								else {
									query.setParameter(params[i], values[i]);
								}
							}
						}
						return query.list();
					}
				}));
	}
	
	@Override
	public List findByQueryPage(String paramString1, int satrt, int size) {
		return findByQueryPage(paramString1, new String[0], new Object[0],satrt,size);
	}

	@Override
	public List findByQueryPage(String paramString1, String paramString2,
			Object paramObject, int satrt, int size) {
		return findByQueryPage(paramString1, new String[]{paramString2}, new Object[]{paramObject},satrt,size);
	}

	@Override
	public List findByQueryPage(final String hql,final String[] params,
			final Object[] values,final int start,final int size) {
		return ((List) getHibernateTemplate().execute(
				new HibernateCallback<Object>() {
					public Object doInHibernate(Session session)
							throws HibernateException, SQLException {
						Query query = session.createQuery(hql);
						query.setFirstResult(start);
						query.setMaxResults(size);
						query.getReturnAliases();
						if (values != null) {
							for (int i = 0; i < params.length; ++i) {
								if (StringUtils.isEmpty(params[i]))
									continue;
								if ((values != null)
										&& (Collection.class
												.isAssignableFrom(values
														.getClass())))
									query.setParameterList(params[i],
											(Collection) values[i]);
								else {
									query.setParameter(params[i], values[i]);
								}
							}
						}
						return query.list();
					}
				}));
		}

	
	public Object findByQueryUniqueResult(final String hql,
			final String[] params, final Object[] values) {
		return getHibernateTemplate().execute(new HibernateCallback() {

			public Object doInHibernate(Session session)
					throws HibernateException, SQLException {
				Query query = session.createQuery(hql);
				query.getReturnAliases();
				if (values != null) {
					for (int i = 0; i < params.length; ++i) {
						if (StringUtils.isEmpty(params[i]))
							continue;
						if ((values != null)
								&& (Collection.class.isAssignableFrom(values
										.getClass())))
							query.setParameterList(params[i],
									(Collection) values[i]);
						else {
							query.setParameter(params[i], values[i]);
						}
					}
				}
				return query.uniqueResult();
			}

		});
	}

	
	public Object findByQueryUniqueResult(String hql, String param, Object value) {
		return findByQueryUniqueResult(hql, new String[] { param },
				new Object[] { value });
	}

	
	public int executeByHql(final String hql, final String[] params,
			final Object[] values) {
		return ((Integer) getHibernateTemplate().execute(
				new HibernateCallback<Object>() {
					public Object doInHibernate(Session session)
							throws HibernateException, SQLException {
						Query query = session.createQuery(hql);
						if (values != null) {
							for (int i = 0; i < params.length; ++i) {
								if (StringUtils.isEmpty(params[i]))
									continue;
								if ((values[i] != null)
										&& (Collection.class
												.isAssignableFrom(values
														.getClass())))
									query.setParameterList(params[i],
											(Collection) values[i]);
								else {
									query.setParameter(params[i], values[i]);
								}
							}
						}
						return Integer.valueOf(query.executeUpdate());
					}
				}));
	}

	
	public int executeByHql(String hql, String parame,
			Object value) {
		return executeByHql(hql, new String[] { parame }, 
				       new Object[] { value });
	}

	@Autowired
	public void setSf(SessionFactory sessionFactory) {
		this.sessionFactory = sessionFactory;
		setHibernateTemplate(createHibernateTemplate(sessionFactory));
	}

	public SessionFactory getSf() {
		return this.sessionFactory;
	}


}
